package ch.dreamweb.readpractice.client.lesetraining.train.presenter;

import java.util.List;

import ch.dreamweb.readpractice.client.lesetraining.Constants;
import ch.dreamweb.readpractice.client.lesetraining.Constants.Position;
import ch.dreamweb.readpractice.client.lesetraining.train.event.CorrectEvent;
import ch.dreamweb.readpractice.client.lesetraining.train.event.CorrectEventHandler;
import ch.dreamweb.readpractice.client.lesetraining.train.event.IncorrectEvent;
import ch.dreamweb.readpractice.client.lesetraining.train.event.IncorrectEventHandler;
import ch.dreamweb.readpractice.client.lesetraining.train.view.Unit3View;
import ch.dreamweb.readpractice.client.lesetraining.train.view.UnitView;
import ch.dreamweb.readpractice.client.managed.request.ApplicationRequestFactory;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HasWidgets;

public class Unit3Presenter extends UnitPresenter implements
		Unit3View.Unit3Presenter {

	private final Unit3View view;
	private int random = 0;
	private int record = 0;
	private final String[] morphems3 = { "", "", "" };
	private int count = 0;
	private final String[] morphems20 = { "", "", "", "", "", "", "", "", "",
			"", "", "", "", "", "", "", "", "", "", "" };

	Timer t = new Timer() {
		@Override
		public void run() {
			Log.info("Timer 3 läuft ab");
			view.setOkEnabled(false);
			view.setMorphem("");
			view.setMorphem3(morphems3[0] + morphems3[1] + morphems3[2]);
			view.setPositionEnabled(true);
			view.setFocusBeginning();
			t.cancel();
		}
	};

	public Unit3Presenter(EventBus eventBus,
			ApplicationRequestFactory requests, Unit3View view) {
		super(eventBus, requests);
		this.view = view;
		this.view.setPresenter(this);
		bind();
	}

	private void bind() {
		getEventBus().addHandler(CorrectEvent.TYPE, new CorrectEventHandler() {

			@Override
			public void onCorrect(CorrectEvent event) {
				// TODO MKE: improve this, not nice but working
				if (event.getUnit() == 3) {
					doCorrect();
				}
			}
		});
		getEventBus().addHandler(IncorrectEvent.TYPE,
				new IncorrectEventHandler() {

					@Override
					public void onIncorrect(IncorrectEvent event) {
						// TODO MKE: improve this, not nice but working
						if (event.getUnit() == 3) {
							doIncorrect(event.getWrong());
						}
					}
				});

	}

	private void doCorrect() {
		view.addInfoNineCorrect(correctMorphems.get(count));
		if (count < (level - 1)) {
			count++;
			comment = commentCorrect();
			view.setInfo(comment, Constants.CORRECT);
			showNine();
		} else {
			record = increaseLevel();
			comment = commentCorrectFinal(record);
			view.setInfo(comment, Constants.CORRECT);
			view.setStartEnabled(true);
			view.setNineEnabled(false);
			newExercice();
		}
	}

	private void doIncorrect(String wrong) {
		String morphem = "";
		morphem = morphems.get(count);
		view.addInfoNineIncorrect(wrong, morphem);
		decreaseLevel();
		Log.info("in Unit3: Level: " + level + "    Step: " + step);
		comment = commentIncorrect();
		view.setInfo(comment, Constants.INCORRECT);
		view.setNineEnabled(false);
		view.setStartEnabled(true);
		newExercice();
	}

	@Override
	protected void init() {
		super.init();

		// Infos aus Datenbank auslesen
		level = editableSetting.getT3level();
		step = editableSetting.getT3step();
		stepsperlevel = editableSetting.getT3stepsperlevel();
		highestlevel = editableSetting.getT3highestlevel();
		higheststep = editableSetting.getT3higheststep();
		highestdaylevel = editableSetting.getT3highestdaylevel();
		highestdaystep = editableSetting.getT3highestdaystep();
		tottime = editableSetting.getT3tottime();
		prestime = editableSetting.getT3prestime();

		// Start exercice
		newExercice();
	}

	@Override
	public void go(final HasWidgets container) {
		super.go(container);
		container.add(view.asWidget());
	}

	@Override
	public void onOkButtonClicked() {
		view.setOkEnabled(false);
		view.setMorphem("");
		view.setMorphem3(morphems3[0] + morphems3[1] + morphems3[2]);
		view.setPositionEnabled(true);
		view.setFocusBeginning();
		t.schedule(prestime);
	}

	@Override
	public void onStartButtonClicked() {
		morphems = info.getMorphems();
		Log.info("Vor Schleife Startbutton");
		for (int i = 0; i < 20; i++) {
			morphems20[i] = morphems.get(i);
			correctMorphems.add(morphems20[i]);
		}
		;
		count = 0;
		view.setStartEnabled(false);
		view.setNineVisible(false);
		view.setInfo("");
		view.setInfoNine("");
		getNextMorphem();
	}

	void getNextMorphem() {
		Log.info("Vor Schleife getNext");
		do {
			random = (int) (Math.random() * (morphems.size() - 2));
		} while ((random <= count) && (random >= (count - 2)));
		Log.info("Nach Schleife getNext");
		morphems3[0] = morphems.get(random);
		morphems3[1] = morphems.get(random + 1);
		morphems3[2] = morphems.get(random + 2);
		random = (int) (Math.random() * 3);
		morphems3[random] = morphems20[count];
		view.setMorphem3("");
		view.setMorphem(morphems20[count]);
		view.setOkEnabled(true);
		t.schedule(prestime);
	}

	@Override
	public void onPositionButtonClicked(Position position) {
		switch (position) {
		case BEGINNING:
			Log.debug("beg.");
			if (random == 0) {
				correctPositionClicked();
			} else {
				incorrectPositionClicked();
			}
			break;
		case MIDDLE:
			Log.debug("mid.");
			if (random == 1) {
				correctPositionClicked();
			} else {
				incorrectPositionClicked();
			}
			break;
		case END:
			Log.debug("end.");
			if (random == 2) {
				correctPositionClicked();
			} else {
				incorrectPositionClicked();
			}
			break;
		default:
			// should not happen
			Log.error("Switch default reached; should not happen");
			return;
		}
	}

	private void correctPositionClicked() {
		Log.info("Position correct.");
		// view.setInfo("Wow, super!!");
		view.setInfo("");
		view.setPositionEnabled(false);
		if (count < (level - 1)) {
			count++;
			getNextMorphem();
		} else {
			count = 0;
			view.setMorphem("");
			view.setMorphem3("");
			showNine();
		}
	}

	private void showNine() {
		assert morphems.size() >= 8 : "not enough morphems";

		// TODO MKE take first ones, not last, or better start with rand and
		// take next 8
		List<String> subList = morphems.subList(morphems.size() - 9,
				morphems.size() - 1);
		String[] others = subList.toArray(new String[0]);
		view.setNine(morphems.get(count), others);
	}

	private void incorrectPositionClicked() {
		Log.info("Position incorrect.");
		view.setInfo("Ooops, leider daneben. Versuch es nochmals.",
				Constants.INCORRECT);
		view.setPositionEnabled(true);
	}

	@Override
	protected void saveStuff() {
		super.saveStuff();

		editableSetting.setT3level(level);
		editableSetting.setT3step(step);
		editableSetting.setT3highestlevel(highestlevel);
		editableSetting.setT3higheststep(higheststep);
		editableSetting.setT3highestdaylevel(highestdaylevel);
		editableSetting.setT3highestdaystep(highestdaystep);
		editableSetting.setT3done(true);

		writeStatistic(3);
	}

	@Override
	protected void newExercice() {
		super.newExercice();
		if (info.isTimeUp(tottime)) {
			Log.info("Time's up... Ending Unit 3");
			saveStuff();
			info.setUnitActive(0);
			view.setMenuVisible(true);
			view.setFocusMenu();
			view.setStartEnabled(false);
		} else {
			count = 0;
			view.setInfoLevel("Level: " + level + " / " + step);
			correctMorphems.clear();
			view.setPositionEnabled(false);
			view.setMorphem("");
			view.setMorphem3("");
			view.setFocusStart();
		}
	}

	@Override
	protected UnitView getView() {
		return view;
	}

	@Override
	protected void showElephant(int type) {
		view.showElephant(type);
	}
}
